package render.tree
{
	import mx.collections.ArrayCollection;
	import mx.collections.ICollectionView;

	public class CategoryNode implements INode,IEditableNode
	{
		private var _children:ArrayCollection = new ArrayCollection();
		
		private var fetchDone:Boolean = false;
		
		protected var pageSize:int;
		
		protected var tree:TreeStructureRender;
		
		protected var _uri:String;
		
		protected var _edge:String;
		
		public function CategoryNode(tree:TreeStructureRender,uri:String,edge:String)
		{
			this.tree = tree;
			this.pageSize = tree.categoryPageSize;
			this._uri = uri;
			this._edge = edge;
		}

		public function getChildren():ICollectionView
		{
			return _children;
		}
		
		public function getChildAt(index:int):INode
		{
			return INode(_children.getItemAt(index));
		}
		
		public function getChildrenAmount():int
		{
			return _children.length;
		}
		
		public function getNodeType():String
		{
			return StructureDescriptor.NODE_TYPE_CATEGORY;
		}
		
		public function getURI():String
		{
			return _uri;
		}
		
		public function addChildAt(node:INode,index:int):void
		{
			return _children.addItemAt(node,index);
		}
		public function removeChildAt(index:int):Boolean{
			return _children.removeItemAt(index);
		}
		
		public function pushItem(node:INode):void
		{
			return _children.addItem(node);
		}
		public function clear():void
		{
			_children.removeAll();
		}
		public function toString():String
		{
			return tree.formatFunction.call(this,getURI());
		}
		
		protected function internalFetch():void
		{
			
			fetchItems(internalFetchHandler,_uri,0,pageSize+1);
			
		}
		private function internalFetchHandler(items:Array):void
		{
			pushItems(items);
			
			if(items.length > pageSize ){
				var pageControl:PageControl = new PageControl(this,_uri,0,pageSize);
				pushItem(pageControl);
			}
			
			sort();
			
			fetchDone = true;

			tree.expandItem(this,false,true);
			tree.validateNow();
			tree.expandItem(this,true,true);
			
		}
		public function getEdge():String
		{
			if(tree.displayEdge)
				return tree.formatFunction.call(this,_edge);
			return null;
		}
		public function fetchItems(handler:Function,uri:String,index:int,size:int):void
		{
			tree.fetcherFunction.call(this,handler,uri,index,size);
		}
		public function pushItems(items:Array):void
		{
			for(var i:int = Math.min(items.length,pageSize) -1 ; i >= 0 ; i--){
				pushItem(createNode(items[i]));
			}
		}
		protected function createNode(object:Object):CategoryNode
		{
			var type:String = object.nodeType;
			var uri:String = object.uri;
			var edge:String = object.edgeName;
			if(type == StructureDescriptor.NODE_TYPE_CATEGORY){
				return new CategoryNode(tree,uri,edge);
			}
			else if (type == StructureDescriptor.NODE_TYPE_ATTRIBUTE){
				return new AttributeNode(tree,uri,edge);
			}
			else if (type == StructureDescriptor.NODE_TYPE_INSTANCE){
				return new InstanceNode(tree,uri,edge);
			}
			
			return null;
		}
		
		public function sort():void
		{
			var cats:Array = new Array();
			var ints:Array = new Array();
			var atts:Array = new Array();
			var page:INode = null;
			
			for each(var node:INode in _children){
				if(node.getNodeType() == StructureDescriptor.NODE_TYPE_CATEGORY)
					cats.push(node);
				else if(node.getNodeType() == StructureDescriptor.NODE_TYPE_ATTRIBUTE)
					atts.push(node);
				else if(node.getNodeType() == StructureDescriptor.NODE_TYPE_INSTANCE)
					ints.push(node);
				else if(node.getNodeType() == StructureDescriptor.NODE_TYPE_PAGECONTORL)
					page = node;
			}
			
			clear();
			
			addNodesAll(cats);
			addNodesAll(ints);
			addNodesAll(atts);
			
			if(page)
				_children.addItem(page);			
		}
		
		public function addNodesAll(array:Array):void
		{
			for each( var obj:Object in array)
				_children.addItem(obj);
		}
		
		public function fetch():void
		{
			if(!fetchDone){
				trace("internal fetch");
				internalFetch();
			}
		}
		public function solid():void
		{
			fetchDone = true;
		}
	}
}